#ifndef _sdl_renderer_h_
#define _sdl_renderer_h_

#include "sdl_debug.h"
#include "sdl_graphic.h"
#include "sdl_vbomap.h"
#include "sdl_mvector.h"
#include "sdl_texdata.h"
#include "sdl_prim.h"
#include "sdl_world.h"
#include "sdl_exceptions.h"
#include "sdl_singleton.h"
#include "sdl_my_opengl.h"
#include "sdl_canvas.h"

namespace sdl_graphic {

    /**
     * \brief bryła wyświetlania
     */
    class frustum {
        mvector4f v_far;
        mvector4f v_near;
        mvector4f v_top;
        mvector4f v_bottom;
        mvector4f v_left;
        mvector4f v_right;
        matrix4x4f projection;
        matrix4x4f modelview;
        matrix4x4f combined;
    public:
        frustum();
        void update(const matrix4x4f &, const matrix4x4f &);
        bool contained(const sdl_ptr<entity> & e);
    };

    /**
     * \brief Bierze scenę i wyświetla
     */
    class renderer : public sdl_layer, public sdl_singleton<renderer>,
    depends<sdl_canvas::screen_info> {
        frustum view;
        sdl_ptr<world> current_world; ///<aktualnie rysowany świat
    public:
        renderer(const std::string & n = "renderer");
        ~renderer();
        void set_world(const sdl_ptr<world> & w);
        void update();

    private:
        //void setup_buffers(int & offset, sdl_ptr<vertex_vmap> & v,sdl_ptr<vertex_vmap> & n, sdl_ptr<color_vmap> & c, std::vector<sdl_ptr<tex_vmap> > & t, sdl_ptr<material> & mat, matrix4x4f & transform) ;
        void setup_buffers(const sdl_ptr<mesh> &);
        void setup_material(const sdl_ptr<material> & mat, const std::vector<sdl_ptr<tex_vmap> > & t);
        void update_draw();
    };

    inline bool frustum::contained(const sdl_ptr<entity> & e) {
        if (!e)return false;
        float rad = e->body->get_radius();
        mvector4f point = e->transform.column(3);
        if (v_right * point <= -rad) return false;
        if (v_left * point <= -rad) return false;
        if (v_top * point <= -rad) return false;
        if (v_bottom * point <= -rad) return false;
        if (v_far * point <= -rad) return false;
        if (v_near * point <= -rad) return false;
        return true;
    }





}; //namespace sdl_graphic

#endif //_sdl_renderer_h_
